package com.webex.ta.hydra.gui.wm;

import com.webex.ta.hydra.gui.GuiPackage;

import javax.swing.*;
import java.util.HashMap;
import java.util.List;

/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-10-20
 * Time: 8:44:38
 */
public class ToolWindowManager {
    private static ToolWindowManager instance = new ToolWindowManager();

    private InstructionProcessor instructionProcessor = new InstructionProcessor();
    private final HashMap<String, InternalDecorator> internalDecorators;
    private final HashMap<String, FloatingDecorator> floatingDecorators;
    private final HashMap<String, SideBarButton> sidebarButtons;
    private ToolWindowPane toolWindowPane;

    private SideStack sideStack;
//    private WindowInfo topWindow, leftWindow, bottomWindow, rightWindow;

    private ToolWindowManager() {
        internalDecorators = new HashMap<String, InternalDecorator>();
        floatingDecorators = new HashMap<String, FloatingDecorator>();
        sidebarButtons = new HashMap<String, SideBarButton>();
        sideStack = new SideStack();
    }

    public static ToolWindowManager getInstance() {
        return instance;
    }

    protected void setToolWindowPane(ToolWindowPane twp) {
        toolWindowPane = twp;
    }

    protected ToolWindowPane getToolWindowPane() {
        return toolWindowPane;
    }


    public void registerToolWindow(String id, JComponent component, int anchor, String title, Icon icon) {
        WindowInfo info = new WindowInfo(id);
        info.setActive(false);
        info.setId(id);
        info.setTitle(title);
        info.setAnchor(anchor);
        final InternalDecorator decorator = new InternalDecorator(component, info);
        new ToolWindowFocusWatcher(decorator);
        internalDecorators.put(id, decorator);
        SideBarButton sideBarButton = new SideBarButton(id, anchor);
        sideBarButton.setText(title);
        sideBarButton.setIcon(icon);
        sidebarButtons.put(id, sideBarButton);
        toolWindowPane.addSideBarButton(sideBarButton);
        decorator.apply(info);
    }

    public void unregisterToolWindow(String id) {
        this.hideToolWindow(id);
        internalDecorators.remove(id);
        SideBarButton sideBarButton = sidebarButtons.get(id);
        toolWindowPane.removeSideBarButton(sideBarButton);
    }

    public FloatingDecorator getFlowingDecorator(final String id) {
        return floatingDecorators.get(id);
    }

    public InternalDecorator getInternalDecorator(final String id) {
        return internalDecorators.get(id);
    }

    public void hideToolWindow(String id) {
        InternalDecorator dec = internalDecorators.get(id);
        if (dec != null) {
            WindowInfo info = dec.getWindowInfo();
            _hideToolWindow(id);
            if (info.getType() != ToolWindowType.FLOATING) {
                // stack management
                WindowInfo top = sideStack.peek(info.getAnchor());
                if (top == null) return;
                if (top.getId().equals(info.getId())) {
                    // it's a top window, show the next in stack 
                    sideStack.remove(id);
                    WindowInfo nextTop = sideStack.pop(info.getAnchor());
                    if (nextTop != null) {
                        _showToolWindow(nextTop.getId());
                    }
                }
            }
        }
        System.out.println(sideStack.size());
    }

    public void showToolWindow(String id) {
        InternalDecorator dec = internalDecorators.get(id);
        if (dec != null) {
            WindowInfo info = dec.getWindowInfo();
            if (info.getType() != ToolWindowType.FLOATING) {
                // stack management
                WindowInfo lastTop = sideStack.peek(info.getAnchor());
                if (lastTop != null && !lastTop.getId().equals(id)) {
//                    sideStack.push(lastTop);
                    _hideToolWindow(lastTop.getId());
                }
                sideStack.push(info);
            }
            _showToolWindow(id);
        }
    }

    public void _deactivateAllToolWindows() {
        for (InternalDecorator dec : internalDecorators.values()) {
            dec.setActive(false);
        }
    }

    public void toggleToolWindow(String id) {
        InternalDecorator dec = internalDecorators.get(id);
        if (dec.getWindowInfo().isVisible()) {
            // hide it
            hideToolWindow(id);
        } else {
            // show it
            showToolWindow(id);
            activateToolWindow(id);
        }
    }

    // atomic hide operation, without stack management
    public void _hideToolWindow(String id) {
        InternalDecorator dec = internalDecorators.get(id);
        if (dec != null) {
            WindowInfo info = dec.getWindowInfo();
            if (info.getType() == ToolWindowType.FLOATING) {
                toolWindowPane.hideFloatingToolWindow(getFlowingDecorator(id));
            } else {
                toolWindowPane.hideSlidingToolWindow(dec);
            }
            info.setVisible(false);

            SideBarButton button = sidebarButtons.get(id);
            if (button != null)
                button.setSelected(false);
        }
    }

    public void _showToolWindow(String id) {
        InternalDecorator dec = internalDecorators.get(id);
        if (dec != null) {
            WindowInfo info = dec.getWindowInfo();
            if (info.getType() == ToolWindowType.FLOATING) {
                FloatingDecorator fd = new FloatingDecorator(GuiPackage.getInstance().getIdeFrame(),
                        getInternalDecorator(id));
                floatingDecorators.put(id, fd);
                toolWindowPane.showFloatingToolWindow(fd);
            } else {
                toolWindowPane.showSlidingToolWindow(dec);
            }
            WindowInfo newInfo = info.copy();
            newInfo.setVisible(true);
            dec.apply(newInfo);
        }
        SideBarButton button = sidebarButtons.get(id);
        if (button != null)
            button.setSelected(true);
    }

    public void activateToolWindow(String id) {
        InternalDecorator dec = internalDecorators.get(id);
        if (dec != null) {
            dec.setActive(true);
            dec.requestFocus();
        }
    }

    public void deactivateToolWindow(String id) {
        InternalDecorator dec = internalDecorators.get(id);
        if (dec != null) {
            dec.setActive(false);
        }
    }

    public void toggleFloatingToolWindow(String id) {
        InternalDecorator dec = internalDecorators.get(id);
        if (dec == null) return;

        hideToolWindow(id);
        
        WindowInfo info = dec.getWindowInfo();
        if (info.isFloating()) {
            info.setType(ToolWindowType.SLIDING);
        } else {
            info.setType(ToolWindowType.FLOATING);
        }

        showToolWindow(id);
        activateToolWindow(id);
    }

    private void execute(List<Instruction> instructions) {
        instructionProcessor.execute(instructions);
    }

//    public WindowInfo getTopWindow(int anchor) {
//        switch (anchor) {
//            case SwingConstants.TOP:
//                return topWindow;
//            case SwingConstants.LEFT:
//                return leftWindow;
//            case SwingConstants.BOTTOM:
//                return bottomWindow;
//            case SwingConstants.RIGHT:
//                return rightWindow;
//            default:
//                return null;
//        }
//    }
//
//    public void setTopWindow(WindowInfo info) {
//        switch(info.getAnchor()) {
//            case SwingConstants.TOP:
//                topWindow = info;
//            case SwingConstants.LEFT:
//                leftWindow = info;
//            case SwingConstants.BOTTOM:
//                bottomWindow = info;
//            case SwingConstants.RIGHT:
//                rightWindow = info;
//        }
//    }
}
